#define _CRT_SECURE_NO_WARNINGS 1

//#include <stdio.h>
//#include <stdlib.h>
//int main(void)
//{
//    // 假设开辟10个整型空间
//    int arr[10]; // 在栈区上开辟
//    // 动态内存开辟
//    int* p = (int*)malloc(10 * sizeof(int)); // 开辟10个大小为int的空间
//    // 使用这些空间的时候
//    if (p == NULL) 
//    {
//        perror("main"); // main: 错误信息
//        return 0;
//    }
//    // 使用
//    int i = 0;
//    for (i = 0; i < 10; i++) 
//    {
//        *(p + i) = i;// p[i]=i;也行
//    }
//    for (i = 0; i < 10; i++) 
//    {
//        printf("%d ", p[i]);
//    }
//    // 回收空间
//    free(p);
//    p = NULL; // 需要手动置为空指针
//    return 0;
//}

//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//    int* p = (int*)calloc(10, sizeof(int));
//    if (p == NULL) 
//    {
//        perror("main");
//        return 0;
//    }
//    for (int i = 0; i < 10; i++)
//    {
//        *(p + i) = 5;
//    }
//    // 此时，这里需要p指向的空间更大，需要20个int的空间
//    // realloc 调整空间
//    //p = (int*)realloc(p, 20 * sizeof(int)); // 调整为20个int的大小的空间
//
//    /*刚才提到的第三种情况，如果 realloc 找不到合适的空间，就会返回空指针。
//    我们想让它增容，他却存在返回空指针的危险，然后我们就找不到原来的空间了
//    解决方案：不要拿指针直接接收 realloc，可以使用临时指针判断一下。*/
//    int* tmp = (int*)realloc(p, 20 * sizeof(int));// 调整为20个int的大小的空间
//    // 如果ptmp不等于空指针，再把p交付给它
//    if (tmp != NULL) 
//    {
//        p = tmp;
//    }
//
//    free(p); // 释放
//    p = NULL; // 置空
//}

//#include <stdlib.h>
//#include <stdio.h>
//int main()
//{
//    int* p = (int*)malloc(9999999999);
//    int i = 0;
//    for (i = 0; i < 10; i++) 
//    {
//        *(p + i) = i; // 对空指针进行解引用操作，非法访问内存
//    }
//    return 0;
//}
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//    int* p = (int*)malloc(10 * sizeof(int)); // 申请10个整型的空间
//    if (p == NULL) 
//    {
//        perror("main");
//        return 1;
//    }
//    int i = 0;
//    // 越界访问 - 指针p只管理10个整型的空间，根本无法访问40个
//    for (i = 0; i < 40; i++)
//    {
//        *(p + i) = i;
//    }
//    free(p);
//    p = NULL;
//    return 0;
//}
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//    int arr[10] = { 0 }; // 在栈区上开辟
//    int* p = arr;
//    // 使用  略
//    free(p); // 使用free释放非动态开辟的空间
//    p = NULL;
//    return 0;
//}
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//    int* p = (int*)malloc(10 * sizeof(int)); // 申请10个整型的空间
//    if (p == NULL) 
//    {
//        perror("main");
//        return 1;
//    }
//    int i = 0;
//    // 越界访问 - 指针p只管理10个整型的空间，根本无法访问40个
//    for (i = 0; i < 40; i++)
//    {
//        *(p + i) = i;
//    }
//    free(p);
//    p = NULL;
//    return 0;
//}
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//    int arr[10] = { 0 }; // 在栈区上开辟
//    int* p = arr;
//    // 使用  略
//    free(p); // 使用free释放非动态开辟的空间
//    p = NULL;
//    return 0;
//}
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//    int* p = malloc(10 * sizeof(int));
//    if (p == NULL) 
//    {
//        return 1;
//    }
//    int i = 0;
//    for (i = 0; i < 5; i++) 
//    {
//        *p++ = i; // p指向的空间被改变了
//        //而且存在内存泄露风险
//    }
//    free(p);//error  p不再指向动态内存的起始位置
//    p = NULL;
//    return 0;
//}
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//    int* p = malloc(10 * sizeof(int));
//    if (p == NULL) 
//    {
//        return 1;
//    }
//    int i = 0;
//    for (i = 0; i < 10; i++) 
//    {
//        p[i] = i;
//    }
//     释放
//    free(p);
//    // 一时脑热或者出了函数后忘了，再一次释放
//    free(p);//error
//    return 0;
//}
//解决方案：在第一次释放后紧接着将 p 置为空指针

//#include <stdio.h>
//#include <stdlib.h>
//void test()
//{
//    int* p = (int*)malloc(100);
//    if (p == NULL)
//    {
//        return;
//    }
//    // 使用 略
//    
//    // 此时忘记释放了
//}
//int main()
//{
//    test();
//    free(p); // 此时释放不了了，没人知道这块空间的起始位置在哪了
//    p = NULL;
//}
//malloc 这一系列函数 和 free 一定要成对使用，记得及时释放。
//你自己申请的空间，用完之后不打算给别人用，就自己释放掉即可。
//如果你申请的空间，想传给别人使用，传给别人时一定要提醒别人用完之后记得释放。
//#include <stdio.h>
//#include <stdlib.h>
//struct S
//{
//    int n;
//    int arr[0];
//};
//int main() 
//{
//    // 期望arr的大小是10个整型
//    struct S* ps = (struct S*)malloc(sizeof(struct S) + sizeof(int));
//    ps->n = 10;
//    // 使用
//    int i = 0;
//    for (i = 0; i < 10; i++)
//    {
//        ps->arr[i];
//    }
//    // 增容
//    struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));
//    if (ptr != NULL)
//    {
//        ps = ptr;
//    }
//    // 再次使用 （略）
//    // 释放
//    free(ps);
//    ps = NULL;
//    return 0;
//}

//第一题问题程序：
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//void GetMemory(char* p)
//{
//    p = (char*)malloc(100);
//}
//void Test()
//{
//    char* str = NULL;
//    GetMemory(str);
//    strcpy(str, "hello world");
//    printf(str);
//}
//int main()
//{
//    Test();
//    return 0;
//}
//解析：（笔试和面试时要能把问题用语言说出来）
//str 传给 GetMemory 函数时为值传递，所以 GetMemory 函数的形参 p 是 str 的一份临时拷贝。
//在 GetMemory 函数内部动态开辟的内存空间的地址存放在了 p 中，并不会影响 str。
//所以当 GetMemory 函数返回之后， str 仍然是 NULL，导致 strcpy 拷贝失败。
//其次，随着 GetMemory 函数的返回，形参 p 随即销毁并且没有及时的使用 free 释放，
//从而导致动态开辟的100个字节存在内存泄露问题。根据经验，程序会出现卡死的问题。
//第一题改法1 ：
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//// ↓ 修改返回类型为char*
//char* GetMemory(char* p)
//{
//    p = (char*)malloc(100);
//    return p; // 将p带回来
//}
//void Test()
//{
//    char* str = NULL;
//    str = GetMemory(str); // 用str接收，此时str指向刚才开辟的空间
//    strcpy(str, "hello world"); // 此时copy就没有问题了
//    printf(str);//printf("hello world");传给printf函数的也是h的地址，所以没问题
//    // 用完之后记得free，就可以解决内存泄露问题
//    free(str);
//    str = NULL; // 还要将str置为空指针
//}
//int main()
//{
//    Test();
//    return 0;
//}
//第一题改法2 ：
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
////              ↓ 用char**接收
//void GetMemory(char** p)
//{
//    *p = (char*)malloc(100);
//}
//
//void Test()
//{
//    char* str = NULL;
//    GetMemory(&str); // 址传递，就可以得到地址
//    strcpy(str, "hello world");
//    printf(str);
//    // 记得free，就可以解决内存泄露问题
//    free(str);
//    str = NULL; // 还要将str置为空指针
//}
//int main()
//{
//    Test();
//    return 0;
//}

//第二题
//#include <stdio.h>
//#include <stdlib.h>
//char* GetMemory(void) 
//{
//    char p[] = "hello world";
//    return p;
//}
//void Test(void) 
//{
//    char* str = NULL;
//    str = GetMemory();
//    printf(str);
//}
//int main() 
//{
//    Test();
//    return 0;
//}

//第三题
//#include <stdio.h>
//#include <stdlib.h>
//void GetMemory(char** p, int num) 
//{
//    *p = (char*)malloc(num);
//}
//void Test(void) 
//{
//    char* str = NULL;
//    GetMemory(&str, 100);
//    strcpy(str, "hello");
//    printf(str);
//}
//int main() 
//{
//    Test();
//    return 0;
//}

//第四题
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//void Test(void) 
//{
//    char* str = (char*)malloc(100);
//    strcpy(str, "hello");
//    free(str);
//    if (str != NULL) 
//    {
//        strcpy(str, "world");
//        printf(str);
//    }
//}
//int main() 
//{
//    Test();
//    return 0;
//}

//#include <stdio.h>
//struct S 
//{
//    int n; // 4
//    int arr[]; // 大小是未知的
//};
//int main() 
//{
//    struct S s = { 0 };
//    printf("%d\n", sizeof(s));//4
//    return 0;
//}

//#include <stdio.h>
//#include <stdlib.h>
//struct S 
//{
//    int n;
//    int arr[0];
//};
//int main() {
//    //期望arr的大小是10个整型           给n的            给arr[]的
//    struct S* ps = (struct S*)malloc(sizeof(struct S) + sizeof(int));
//    // 后面+的大小就是给柔性数组准备的
//    return 0;
//}

//#include <stdio.h>
//#include <stdlib.h>
//struct S
//{
//    int n;
//    int arr[0];
//};
//int main() 
//{
//    // 期望arr的大小是10个整型
//    struct S* ps = (struct S*)malloc(sizeof(struct S) + sizeof(int));
//    ps->n = 10;
//    // 使用
//    int i = 0;
//    for (i = 0; i < 10; i++)
//    {
//        ps->arr[i];
//    }
//    // 增容
//    struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));
//    if (ptr != NULL)
//    {
//        ps = ptr;
//    }
//    // 再次使用 （略）
//    // 释放
//    free(ps);
//    ps = NULL;
//    return 0;
//}

//#include <stdio.h>
//#include <stdlib.h>
//struct S 
//{
//    int n;
//    int* arr;
//};
//int main() 
//{
//    struct S* ps = (struct S*)malloc(sizeof(struct S));
//    if (ps == NULL)
//        return 1;
//    ps->n = 10;
//    ps->arr = (int*)malloc(10 * sizeof(int));
//    if (ps->arr == NULL)
//        return 1;
//    // 使用
//    int i = 0;
//    for (i = 0; i < 10; i++) 
//    {
//        ps->arr[i];
//    }
//    // 增容
//    int* ptr = (struct S*)realloc(ps->arr, 20 * sizeof(int));
//    if (ptr != NULL) 
//    {
//        ps->arr = ptr;
//    }
//    // 再次使用 （略）
//    // 释放
//    free(ps->arr); // 先free第二块空间
//    ps->arr = NULL;
//    free(ps);
//    ps = NULL;
//    return 0;
//}

#include <stdio.h>
#include <stdlib.h>
struct S
{
    int n;
    int arr[0];
};
int main()
{
    // 期望arr的大小是10个整型
    struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
    if (ps == NULL)
    {
        printf("malloc fail\n");
        return -1;
    }
    ps->n = 10;
    // 使用
    for (int i = 0; i < 10; i++)
    {
        ps->arr[i] = i;
    }
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", ps->arr[i]);
    }
    // 增容
    struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));
    if (ptr != NULL)
    {
        ps = ptr;
    }
    // 再次使用 （略）
    // 释放
    free(ps);
    ps = NULL;
    return 0;
}